/**
 * Projekt do předmetu GJA - LATEX TABLE CREATOR
 *
 * Soubor: AttributiveCellTableModel.java
 *
 * @author Ondřej Kubal  <xkluba00@stud.fit.vutbr.cz>
 * @author Petr Šimon    <xsimon10@stud.fit.vutbr.cz>
 */

package table;

import java.util.*;
import java.awt.*;
import javax.swing.table.*;
import javax.swing.event.*;

/**
 * Implementace modelu pro <code>MultiSpanCellTable</code> zpravující attributy buněk:
 *   - podpora slučování buněk
 *   - individuální vzhled buňek (písma, rámečky, barvy pro každou buňku zvlášť)
 *   - prodpora pro "RowHeader"
 *   - odstranění některých bugů JTable
 *   - kopírování dat z/do schránky (Excell)
 */
public class AttributiveCellTableModel extends DefaultTableModel
{
     //** Uchovávání dat */
     protected CellAttribute cellAtt;
     
     /**
      * Konstruktor.
      * Prázdný model.
      */
     public AttributiveCellTableModel()
     {
          this((Vector)null, 0);
     }
     
     /**
      * Konstruktor.
      * @param numRows počet řádků
      * @param numColumns počet sloupců
      */
     public AttributiveCellTableModel(int numRows, int numColumns)
     {
          Vector names = new Vector(numColumns);
          names.setSize(numColumns);
          setColumnIdentifiers(names);
          dataVector = new Vector(numRows);
          dataVector.setSize(numRows);
          setNumRows(numRows);
          cellAtt = new DefaultCellAttribute(numRows, numColumns);
     }
     
     /**
      * Konstruktor.
      * @param columnNames Názvy sloupců
      * @param numRows počet řádků
      */
     public AttributiveCellTableModel(Vector columnNames, int numRows)
     {
          setColumnIdentifiers(columnNames);
          dataVector = new Vector();
          setNumRows(numRows);
          cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
     }
     
     /**
      * Konstruktor.
      * @param columnNames Názvy sloupců
      * @param numRows počet řádků
      */
     public AttributiveCellTableModel(Object[] columnNames, int numRows)
     {
          this(convertToVector(columnNames), numRows);
     }
     
     /**
      * Konstruktor.
      * @param data datový vektor.
      * @param columnNames názvy sloupců.
      */
     public AttributiveCellTableModel(Vector data, Vector columnNames)
     {
          super.setDataVector(data, columnNames);
          mySetDataVector(data, columnNames);
     }
     
     /**
      * Konstruktor.
      * @param data dvourozměrné pole dat
      * @param columnNames Názvy sloupců
      */
     public AttributiveCellTableModel(Object[][] data, Object[] columnNames)
     {
          super.setDataVector(data, columnNames);
          doChange(data.length, columnNames.length);
     }
     
     /**
      * Nastaví data do modelu.
      * @param newData
      * @param columnNames Názvy sloupců
      */
     private void mySetDataVector(Vector newData, Vector columnNames)
     {
          if (newData == null) throw new IllegalArgumentException("setDataVector() - Null parameter");
          
          if (columnNames != null) setColumnIdentifiers(columnNames);
          
          dataVector = newData;
          
          doChange(dataVector.size(), columnIdentifiers.size());
     }
     
     /**
      * Znovuvytvoří datový model.
      * Volat jen při inicializaci !!!!!!.
      * @param dataSize počet řádků
      * @param columnSize počet sloupců
      */
     private void doChange(int dataSize, int columnSize)
     {
          cellAtt = new DefaultCellAttribute(dataSize, columnSize);
          
          newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
     }
     
     /**
      * Přidá nový sloupec
      * @param columnName Název sloupce
      * @param columnData Hodnoty sloupce
      */
     @Override public void addColumn(Object columnName, Vector columnData)
     {
          if (columnName == null) throw new IllegalArgumentException("addColumn() - null parameter");
          
          columnIdentifiers.addElement(columnName);
          int index = 0;
          Enumeration enumeration = dataVector.elements();
          
          while (enumeration.hasMoreElements())
          {
               Object value;
               
               if ((columnData != null) && (index < columnData.size()))
                    value = columnData.elementAt(index);
               else
                    value = null;
                    
               ((Vector)enumeration.nextElement()).addElement(value);
               index++;
          }
          
          cellAtt.addColumn();
//doChange(dataVector.size(),columnIdentifiers.size());

          fireTableStructureChanged();
     }
     
     /**
      * Odstraní sloupec s daným indexem
      * @param index sloupce
      * @return true, pokud lze odebrat sloupec
      */
     public boolean removeColumn(int index)
     {
     
          if (!cellAtt.removeColumn(index)) return false; // odstraníme sloupec atributů, pokud lze odstranit
          
//sloupec atributů byl úspěšně odstraněn
          columnIdentifiers.removeElementAt(index);
          Enumeration enumeration = dataVector.elements();
          
          while (enumeration.hasMoreElements())
          {
               ((Vector)enumeration.nextElement()).removeElementAt(index);
          }
          
          fireTableStructureChanged();
          return true;
     }
     
     
     /**
      * Přidá nový řádek na konec.
      * @param rowData data řádku
      */
     @Override public void addRow(Vector rowData)
     {
          Vector newData = null;
          
          if (rowData == null)
          {
               newData = new Vector(getColumnCount());
          }
          else
          {
               rowData.setSize(getColumnCount());
          }
          
          dataVector.addElement(newData);
          
//
          cellAtt.addRow();
          
          newRowsAdded(new TableModelEvent(this, getRowCount() - 1, getRowCount() - 1,
                                           TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
     }
     
     /**
      * Odstraní vybraný řádek.
      * @param index řádku
      */
     @Override public void removeRow(int index)
     {
          if (!cellAtt.removeRow(index)) return; //nelze provést ostranění řádku
          
          dataVector.removeElementAt(index);
          fireTableStructureChanged();
     }
     
     /**
      * Přístup k jednotlivým attributům.
      */
     public CellAttribute getCellAttribute()
     {
          return cellAtt;
     }
     
     /**
      * Nastaví datavou strukturu pro uchovávání atributů.
      * @param newCellAtt data
      */
     public void setCellAttribute(CellAttribute newCellAtt)
     {
          int numColumns = getColumnCount();
          int numRows = getRowCount();
          
          if ((newCellAtt.getSize().width != numColumns) ||
                    (newCellAtt.getSize().height != numRows))
          {
               newCellAtt.setSize(new Dimension(numRows, numColumns));
          }
          
          cellAtt = newCellAtt;
          fireTableDataChanged();
     }
     
}

